﻿using System;
using System.Collections.Generic;
using System.Net;


namespace Twitter.Net.Status
{
	public class StatusProvider : TwitterProvider
	{
		private const string DESTROY_STATUS_URL = "http://twitter.com/statuses/destroy/{0}.{1}";
		private const string FRIENDS_TIMELINE_URL = "http://twitter.com/statuses/friends_timeline.{0}";
		private const string PUBLIC_TIMELINE_URL = "http://twitter.com/statuses/public_timeline.{0}";
		private const string REPLIES_URL = "http://twitter.com/statuses/replies.{0}";
		private const string SHOW_URL = "http://twitter.com/statuses/show/{0}.{1}";
		private const string UPDATE_STATUS_URL = "http://twitter.com/statuses/update.{0}";
		private const string USER_TIMELINE_URL = "http://twitter.com/statuses/user_timeline.{0}";

		/// <summary>
		/// Initializes a new instance of the <see cref="StatusProvider"/> class.
		/// </summary>
		public StatusProvider()
		{

		}

		/// <summary>
		/// Initializes a new instance of the <see cref="StatusProvider"/> class.
		/// </summary>
		/// <param name="username">The username.</param>
		/// <param name="password">The password.</param>
		public StatusProvider(string username, string password) 
			: base(username, password) 
		{ 

		}

		#region Status Methods

		#region Destroy Status Methods

		/// <summary>
		/// Destroys the status.
		/// </summary>
		/// <param name="format">The format.</param>
		/// <param name="statusID">The status ID.</param>
		/// <returns></returns>
		public string DestroyStatus(ResponseFormat format, int statusID)
		{
			if (format != ResponseFormat.xml && format != ResponseFormat.json)
			{
				throw new ArgumentException("Invalid format specified.  Please specify xml or json.");
			}

			string url = string.Format(DESTROY_STATUS_URL, statusID, format.ToString());
			HttpStatusCode statusCode;
			string data = GetData(url, Username, Password, out statusCode);
			return data;
		}

		#endregion Destroy Status Methods

		#region Friends Timeline Methods

		/// <summary>
		/// Returns the 20 most recent statuses posted in the last 24 hours from the authenticating user and that user's friends.
		/// </summary>
		/// <param name="format">The format.</param>
		/// <returns></returns>
		public string GetFriendsTimeline(ResponseFormat format)
		{
			string url = string.Format(FRIENDS_TIMELINE_URL, format.ToString());
			HttpStatusCode statusCode;
			string data = GetData(url, Username, Password, out statusCode);
			return data;
		}

		#endregion Friends Timeline Methods

		#region Public Timeline Methods

		/// <summary>
		/// Returns the 20 most recent statuses from non-protected users who have set a custom user icon.  Does not require authentication.
		/// </summary>
		/// <param name="format">The format.</param>
		/// <returns></returns>
		public string GetPublicTimeline(ResponseFormat format)
		{
			return GetPublicTimeline(format, 0);
		}

		/// <summary>
		/// Returns the 20 most recent statuses from non-protected users who have set a custom user icon.  Does not require authentication.
		/// </summary>
		/// <param name="format">The format.</param>
		/// <param name="sinceID">Optional.  Returns only public statuses with an ID greater than (that is, more recent than) the specified ID.</param>
		/// <returns></returns>
		public string GetPublicTimeline(ResponseFormat format, int sinceID)
		{
			string url = string.Format(PUBLIC_TIMELINE_URL, format.ToString());
			if (sinceID > 0)
			{
				url = string.Format("{0}?since_id={1}", url, sinceID);
			}

			HttpStatusCode statusCode;

			return GetData(url, out statusCode);
		}

		#endregion Public Timeline Methods

		#region Reply Methods

		/// <summary>
		/// Returns the 20 most recent replies (status updates prefixed with @username posted by users who are 
		/// friends with the user being replied to) to the authenticating user.  Replies are only available to 
		/// the authenticating user; you can not request a list of replies to another user whether public or protected.
		/// </summary>
		/// <param name="format">The format.</param>
		/// <returns></returns>
		public string GetReplies(ResponseFormat format)
		{
			string url = string.Format(REPLIES_URL, format.ToString());
			HttpStatusCode statusCode;
			string data = GetData(url, Username, Password, out statusCode);
			return data;
		}

		#endregion Reply Methods

		#region Show Status Methods

		/// <summary>
		/// Returns a single status, specified by the id parameter below.  The status's author will be returned inline.
		/// </summary>
		/// <param name="format">The format.  xml and json are valid.</param>
		/// <param name="statusID">The numerical ID of the status you're trying to retrieve..</param>
		/// <returns></returns>
		public string GetStatus(ResponseFormat format, int statusID)
		{
			if (format != ResponseFormat.xml && format != ResponseFormat.json)
			{
				throw new ArgumentException("Invalid format specified.  Please specify xml or json.");
			}

			string url = string.Format(SHOW_URL, statusID, format.ToString());
			HttpStatusCode statusCode;
			string data = GetData(url, Username, Password, out statusCode);
			return data;
		}

		#endregion Show Status Methods

		#region Update Status Methods

		/// <summary>
		/// Updates the authenticating user's status.
		/// </summary>
		/// <param name="format">The format.</param>
		/// <param name="status">The text of your status update.  Be sure to URL encode as necessary.  
		/// Must not be more than 160 characters and should not be more than 140 characters to ensure optimal display.</param>
		/// <returns></returns>
		public string UpdateStatus(ResponseFormat format, string status)
		{
			if (format != ResponseFormat.xml && format != ResponseFormat.json)
			{
				throw new ArgumentException("Invalid format specified.  Please specify xml or json.");
			}

			if (string.IsNullOrEmpty(status) || status.Length >= 160)
			{
				throw new ArgumentException("Invalid status.  Status must not be longer than 160 character.  No more than 140 is recommended.");
			}

			string url = string.Format(UPDATE_STATUS_URL, format.ToString());
			HttpStatusCode statusCode;

			//setup the post parameters
			Dictionary<string, string> postParams = new Dictionary<string, string>();
			postParams.Add("status", status);

			string data = PostData(url, postParams, Username, Password, out statusCode);
			return data;
		}

		#endregion Update Status Methods

		#region User Timeline Methods

		public string GetUserTimeline(ResponseFormat format)
		{
			string url = string.Format(USER_TIMELINE_URL, format.ToString());
			HttpStatusCode statusCode;
			string data = GetData(url, Username, Password, out statusCode);
			return data;
		}

		#endregion User Timeline Methods

		#endregion Status Methods
	}
}
